var App = {};
App.modules = {};
App.modules.ticket = {};
App.modules.reveal = {};
App.modules.host = {};
App.modules.deck = {};
App.modules.game = {};
App.modules.reset = {};

App.debug = true;

App.log = function() {
	if(App.debug) {
		console.log.apply(console, arguments);
	}
};

App.on = function(eventName, _callback) {
	var eventId = Math.round(Math.random() * 1000);
	$("#app").on(eventName + "." + eventId, function(e, data){
		App.log("on ->", eventName, "with", data);
		if(_.isFunction(_callback)){
			_callback(data);
		}
	});
	return eventId;
};

App.off = function(eventName, _callback) {
	App.log("off ->", eventName);
	$("#app").off(eventName);
};

App.trigger = function(eventName, data) {
	App.log("trigger ->", eventName, "with", data);
	$("#app").trigger(eventName, data);
};

// Send a message and triggers an event in the sender of the same type.
App.sendMessage = function(message){
  if(message.hasOwnProperty("event") && message.hasOwnProperty("data")){
    if(message.data.hasOwnProperty("gameStatus")){
      App.trigger(message.event,message.data.gameStatus);
    }
  }
  gapi.hangout.data.sendMessage(message);
};

App.modules.reveal.clicked = function() {
	App.trigger("finishGame");
}

App.modules.reveal.init = function() {
	console.log("init reveal");

	if(App.isHost() === true) {
		console.log("You have reveal privileges");
		$("#reveal").click(App.modules.reveal.clicked);
	}
};

console.log("reveal " + App.modules.reveal);

App.modules.river = (function(App, $, _){

	'user strict';

	var river = {};
	var moduleName = "river"; // define a unique module name

	/* ==== PLACE MODULE CODE HERE ==== */

	/* onClick of a card, put your own photo next to the card. */

	/* When the host notifies everyone that the game has finished, get what people
	voted for and display them in the divs. */	
	river.finishGame = function(gameStatus){
		river.result = {"1":[],"3":[],"5":[],"13":[],"21":[],"55":[],"?":[]};

		_.each(gameStatus, function(participantId, participantStatus){
			if(participantStatus.cardSelected !== null){
				App.log("participantId " + participantId);
				App.log("participantStatus " + participantStatus);
				participantImageURL = gapi.hangout.getParticipantById(participantId).image.url;
				river.result[participantStatus.cardSelected].push(participantImageURL);
			}
		});

		river.reset();

		_.each(river.result, function(cardValue, participantList){
			_.each(participantList, function(participantImageURL){
				imageTag = "<img src=\"" + participantImageURL + "\">";
				$("#" + cardValue + "-river").append(imageTag);
			});
		});
	}

	var ractive;

	river.update = function(dataTurns) {
		ractive.set("data.cards", dataTurns)
	}

	river.reset = function() {
		// CLear the river.
		$(".river").html("");
	}

	// default initialisation method (called when API and DOM are ready)
	river.init = function() {

		console.log("init river");

		ractive = new Ractive({
		  el: $("#river"),
		  template: $("#river").html(),
		  data: {
		  	cards: []
		  }
		});

		App.on("dataTurns", river.update);
		App.on("gameStarted", river.reset);
		App.on("gameFinished", river.finishGame);
	};

	/* ================================ */

	return river;

}(App || {}, $, _));

console.log("river " +App.modules.river);

var sender = false;

App.modules.ticket.changed = function(e) {
	var ticketValue = JSON.parse(e.message);
	if(sender === false) {
		$("#ticket").val(ticketValue);
	} else {
		sender = false;
	}
};

// a public method example
App.modules.ticket.change = function() {
	gapi.hangout.data.sendMessage(JSON.stringify({ticketValue: $("#ticket").val()}));
	sender = true;
};

// default initialisation method (called when API and DOM are ready)
App.modules.ticket.init = function() {
	console.log("init ticket");

	$("#ticket").width(472);
	$("#ticket").keyup(App.modules.ticket.change);
	gapi.hangout.data.onMessageReceived.add(App.modules.ticket.changed);
};

console.log("ticket " + App.modules.ticket);

App.modules.host.startGame = function() {

	var participants;
	var participant;

	participants = gapi.hangout.getEnabledParticipants();

	App.modules.host.gameStatus = {};

	// default the card choice of each participant to null
	for(var i=0; i < participants.length; i++) {
		participant = participants[i];
		App.modules.host.gameStatus[participant.id] = {
			cardSelected: null,
			ts: null
		};
	}

	App.log("HOST gameStarted", App.modules.host.gameStatus);

	App.sendMessage(JSON.stringify({
		event: "gameStarted",
		data: {
			gameStatus: App.modules.host.gameStatus
		}
	}));

	$("#reveal").show();
};

App.modules.host.updateGame = function(participantStatus) {
	if(App.modules.host.hasOwnProperty("gameStatus")) {
		App.modules.host.gameStatus[participantStatus.participantId] = {
			cardSelected: participantStatus.cardSelected,
			ts: participantStatus.ts
		};

		App.log("HOST gameUpdated", App.modules.host.gameStatus);

		App.sendMessage(JSON.stringify({
			event: "gameUpdated", 
			data: { gameStatus: App.modules.host.gameStatus }
		}));

		App.modules.host.isGameFinished();

	} else {
		// user is not in the current game
		// or a game hasn't been started
	}
};

App.modules.host.isGameFinished = function() {
		var cardsSelectedCount = 0;
	var participantsCount = App.modules.host.gameStatus.length;
	_.each(App.modules.host.gameStatus, function(participantStatus, participantId){
		if(participantStatus.cardSelected !== null){
			cardsSelectedCount++;
		}
	});
	if(participantsCount <= cardsSelectedCount) {
		App.modules.host.finishGame();
	}
};

App.modules.host.finishGame = function() {

	App.log("HOST gameFinished", App.modules.host.gameStatus);

	App.sendMessage(JSON.stringify({
		event: "gameFinished",
		data: {
			gameStatus: App.modules.host.gameStatus
		}
	}));
};

App.modules.host.parseMessage = function(message) {
	var msg = JSON.parse(message.message);
	var participantStatus = {};
	console.log("HOST message received, is it gameParticipantStatus?", msg.event);
	if(msg.hasOwnProperty("event")) {
		if(msg.event === "gameParticipantStatus") {
			participantStatus.cardSelected = msg.data.cardSelected;
			participantStatus.participantId = msg.data.participantId;
			participantStatus.ts = (new Date()).getTime();			
			App.modules.host.updateGame(participantStatus);
		}
	}
};

App.modules.host.bindEvents = function() {

	// listen for user status
	gapi.hangout.data.onMessageReceived.add(App.modules.host.parseMessage);

	// at any time host can reveal/reset game
	App.on("startGame", App.modules.host.startGame);
	App.on("finishGame", App.modules.host.finishGame);

};

	// default initialisation method (called when API and DOM are ready)
App.modules.host.init = function() {
	console.log("init host");

	if( App.isHost() === true) {
		console.log("binding host events");
		App.modules.host.bindEvents();
	}
};

console.log("host " + App.modules.host);


App.modules.game = (function(App, $, _){

	'user strict';

	var game = {};
	var moduleName = "game"; // define a unique module name

	game.parseMessage = function(message) {

		var msg = JSON.parse(message.message);

		console.log(msg);
		console.log(msg.event);

		if(msg.hasOwnProperty("event")) {
			
			// clean
			if(msg.event === "gameStarted") {

				App.trigger("gameStarted", {
					gameStatus: msg.data.gameStatus
				});

			}

			// reveal
			if(msg.event === "gameFinished") {

				App.trigger("gameFinished", {
					gameStatus: msg.data.gameStatus
				});
			}

			// interact
			if(msg.event === "gameUpdated") {

				App.trigger("gameUpdated", {
					gameStatus: msg.data.gameStatus
				});
				
			}

		}

	};

	game.updateGame = function(participantStatus) {

		App.log("GAME updateGame", participantStatus);		

		gapi.hangout.data.sendMessage(JSON.stringify({
			event: "gameParticipantStatus",
			data: {
				participantStatus: participantStatus
			}
		}));		

	};

	game.init = function() {

		console.log("init game");

		// handle communication coming in
		gapi.hangout.data.onMessageReceived.add(game.parseMessage);

		// handle communication coming out
		App.on("gameParticipantStatus", game.updateGame);

	};

	return game;

}(App || {}, $, _));

console.log("game " + App.modules.game);

App.modules.deck = {};

App.modules.deck.init = function() {

	console.log("init deck");

	// reset the deck on game start/reset
	App.on("gameStarted", App.modules.deck.reset);

	// bind on click event
	$("#deck .card").click(App.modules.deck.clicked);

	// extract default intro
	defaultIntro = $("#deck .intro").val();

};

App.modules.deck.reset = function() {
	$("#deck .sleeve .card").removeClass("selected");
	//("#deck .intro").val(defaultIntro);
};

App.modules.deck.clicked = function(e) {

	console.log("clicked deck");
	
	// extract card's value
	var $card = $(e.currentTarget);
	var value = $card.html();

	//$("#deck .intro").html("Your current estimation: " + value);

	$("#deck .sleeve .card").removeClass("selected");
	$card.addClass("selected");

	// Display avatar of person next to choice.
	$(".river img[class='" + gapi.hangout.getLocalParticipantId() + "']").remove();
	$card.siblings(".river").html("<img class='" + gapi.hangout.getLocalParticipantId() + "' src='" + gapi.hangout.getLocalParticipant().person.image.url + "' />");

	App.log(gapi.hangout.getLocalParticipantId(), "selected", value);

	App.trigger("gameParticipantStatus", {
		participantId: gapi.hangout.getLocalParticipantId(),
		cardSelected: value
	});

};

console.log("deck " + App.modules.deck);

App.modules.reset = {};

App.modules.reset.clicked = function() {
	App.trigger("startGame");
};

App.modules.reset.init = function() {
	console.log("init reset");

	if( App.isHost() === true) {
		console.log("You have reset privileges");
		$("#reset").click(App.modules.reset.clicked);
		$("#reset").show();
	} 
};

console.log("reset " + App.modules.reset);

App = (function(App, $, _){

	'use strict';

	App.isHost = function() {

		var hostId = gapi.hangout.data.getValue("hostId");
		var isHostStillPresent = gapi.hangout.getParticipantById(hostId);

		/*App.log("participants", gapi.hangout.getEnabledParticipants());
		App.log("hostId", hostId);*/

		if(!isHostStillPresent) {
			
			App.log("host is not present anymore");
			App.log("You can be the host");

			gapi.hangout.data.setValue("hostId", gapi.hangout.getLocalParticipantId());

			return true;

		} else {
			if(gapi.hangout.getLocalParticipantId() === hostId){
				return true;
			} else {
				return false;
			}
		}

	};

	App.initVideo = function() {
		console.log("init video");

		var canvas = gapi.hangout.layout.getVideoCanvas();

		canvas.setWidth(550);
		canvas.setPosition(0, 14);
		canvas.setVisible(true);
	}

	/* Reset logic!!! */



	App.init = function() {
		console.log("init app");

		if(App.isHost()){
			App.log("You're the host.");
		} else {
			App.log("You're not the host.")
		}

		if( App.isHost() === true) {
			$('#info-bar').show();
		}

		// initialize modules
		App.initVideo(); // replaced video.js with this.

		App.modules.deck.init();
		App.modules.game.init();
		App.modules.host.init();
		App.modules.reset.init();
		App.modules.reveal.init();
		App.modules.river.init();
		App.modules.ticket.init();
/*
		_.each(App.modules, function(module){
			if(module.hasOwnProperty("init")) {
				if(_.isFunction(module.init)) module.init();
			}
		});*/
	};

	// initialize App once API is ready
	gapi.hangout.onApiReady.add(function(){
		App.init();
	});

	return App;

}(App || {}, $, _));